package co.baiku.boot.aliyun;

import co.baiku.boot.common.exception.ApiException;
import co.baiku.boot.common.spring.SpringContext;
import co.baiku.boot.common.tools.JsonTools;
import co.baiku.boot.common.tools.StringTools;
import co.baiku.boot.common.type.TimeFormat;
import co.baiku.boot.config.AliyunOssConfig;
import co.baiku.boot.message.OssResult;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.InputStream;
import java.net.URL;
import java.time.LocalDateTime;

/**
 * 阿里云对象存储插件
 */
@Component
@ConditionalOnProperty("ajavaer.aliyun.oss.access-key-id")
public class AliyunOss implements InitializingBean {

    private Logger log = LoggerFactory.getLogger(AliyunOss.class);
    @Resource
    private Environment environment;
    @Resource
    private AliyunOssConfig ossConfig;

    private OSS ossClient = null;

    private Boolean isDebug = true;

    public AliyunOss() {
    }

    public AliyunOss(AliyunOssConfig ossConfig) {
        this.ossConfig = ossConfig;
        this.afterPropertiesSet();
    }

    /**
     * 创建存储空间
     *
     * @param request
     * @return
     */
    public Bucket createBucketRequest(CreateBucketRequest request) {
        return ossClient.createBucket(request);
    }

    /**
     * 存储空间是否存在
     *
     * @param bucketName
     * @return
     */
    public boolean doesBucketExist(String bucketName) {
        return ossClient.doesBucketExist(bucketName);
    }

    /**
     * 设置存储空间管理权限
     *
     * @link https://help.aliyun.com/document_detail/145210.html?spm=a2c4g.11186623.6.929.5c0d71ad0YFSJc
     */
    public void setBucketAcl(SetBucketAclRequest setBucketAclRequest) {
        ossClient.setBucketAcl(setBucketAclRequest);
    }

    /**
     * 获取存储空间的地域
     *
     * @param bucketName
     * @return
     */
    public String getBucketLocation(String bucketName) {
        return ossClient.getBucketLocation(bucketName);
    }

    /**
     * 获取存储空间的信息
     *
     * @param bucketName
     * @return
     */
    public BucketInfo getBucketInfo(String bucketName) {
        return ossClient.getBucketInfo(bucketName);
    }

    /**
     * 上传文件
     *
     * @param objectName  bucket name
     * @param inputStream 文件流
     * @param metadata    文件设置参数
     * @return
     */
    public OssResult putObject(String objectName, InputStream inputStream, ObjectMetadata metadata) {
        try {
            if (objectName.startsWith(StringTools.VIRGULE)) {
                objectName = objectName.substring(1);
            }
            PutObjectResult putObjectResult = ossClient.putObject(this.ossConfig.getBucket(), objectName, inputStream, metadata);
            String url = "https://" + this.ossConfig.getBucket() + "." + (this.ossConfig.getEndpoint().contains("http") ? this.ossConfig.getEndpoint().substring(this.ossConfig.getEndpoint().indexOf("oss")) : this.ossConfig.getEndpoint()) + StringTools.VIRGULE + objectName;
            OssResult ossResult = new OssResult();
            ossResult.setUrl(url);
            ossResult.setPath(objectName);
            ossResult.seteTag(putObjectResult.getETag());
            if (isDebug) {
                log.debug("Oss上传成功:" + JsonTools.beanToJson(ossResult));
            }
            return ossResult;
        } catch (Exception e) {
            log.error("系统异常:" + e.getMessage(), e);
            throw ApiException.of("上传失败，请检查阿里云OSS配置");
        }
    }

    /**
     * 上传文件
     *
     * @param objectName
     * @param inputStream
     * @return
     */
    public OssResult putObject(String objectName, InputStream inputStream) {
        return putObject(objectName, inputStream, null);
    }

    /**
     * 获取对象
     *
     * @param objectName
     * @return
     */
    public OSSObject getObject(String objectName) {
        return ossClient.getObject(this.ossConfig.getBucket(), objectName);
    }

    /**
     * 使用签名URL临时授权
     *
     * @param objectName
     * @param urlTokenExpire
     * @see <a href='https://help.aliyun.com/document_detail/32016.html?spm=a2c4g.11186623.6.1006.16843c3cj6j60J'>文档</a>
     */
    public String generatePresignedUrl(String objectName, LocalDateTime urlTokenExpire) {
        URL url = ossClient.generatePresignedUrl(this.ossConfig.getBucket(), objectName, TimeFormat.toDate(urlTokenExpire));
        if (url == null) {
            throw ApiException.of("获取文件访问链接失败，请检查阿里云OSS配置");
        }
        return url.toString();
    }

    /**
     * 使用签名URL临时授权
     *
     * @param request
     * @see <a href='https://help.aliyun.com/document_detail/32016.html?spm=a2c4g.11186623.6.1006.16843c3cj6j60J'>文档</a>
     */
    public String generatePriesignedUrl(GeneratePresignedUrlRequest request) {
        URL url = ossClient.generatePresignedUrl(request);
        if (url == null) {
            throw ApiException.of("获取文件访问链接失败,请检查阿里云OSS配置");
        }
        return url.toString();
    }

    /**
     * 使用签名URL临时授权
     *
     * @param objectName
     * @see <a href='https://help.aliyun.com/document_detail/32016.html?spm=a2c4g.11186623.6.1006.16843c3cj6j60J'>文档</a>
     */
    public String generatePresignedUrl(String objectName) {
        return generatePresignedUrl(objectName, LocalDateTime.now().plusSeconds(ossConfig.getUrlTokenExpire() / 1000L));
    }

    /**
     * 删除单个资源
     *
     * @see <a href='https://help.aliyun.com/document_detail/84842.html?spm=a2c4g.11186623.6.684.56a1412fuWuwdY'>文档</a>
     */
    public void deleteObject(String objectName) {
        ossClient.deleteObject(ossConfig.getBucket(), objectName);
    }

    /**
     * 通过url得到objectName
     *
     * @param url
     * @return
     */
    public String url2ObjectName(String url) {
        //不能为空
        if (StringTools.isBlank(url)) {
            return "";
        }
        //需要包含桶名和endpint
        if (!url.contains("://" + this.ossConfig.getBucket()) || !url.contains(StringTools.VIRGULE + this.ossConfig.getEndpoint() + StringTools.VIRGULE)) {
            return "";
        }
        url = url.replace("https://", "");
        return url.substring(url.indexOf(StringTools.VIRGULE));

    }

    public AliyunOssConfig getOssConfig() {
        return ossConfig;
    }


    public OSS getOssClient() {
        return ossClient;
    }

    @Override
    public void afterPropertiesSet() {
        ossClient = new OSSClientBuilder().build(ossConfig.getEndpoint(), ossConfig.getAccessKeyId(), ossConfig.getAccessKeySecret());
        if (this.environment == null) {
            this.environment = SpringContext.env();
        }
        this.isDebug = this.environment.getProperty("ajavaer.debug", Boolean.class, true);
        if (isDebug) {
            log.debug("Aliyun Oss init");
        }
    }
}
